package com.unknowpupil.sell.exception;

import com.unknowpupil.sell.common.request.Result;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;


/**
 * @Classname: ExceptionHadlers
 * @Author: <a> w10g </a>
 * @CreateDate: Create in 2019/10/8 18:02
 * @Description:  //全局异常拦截
 * @Version: 1.0
 */

@RestControllerAdvice
public class ExceptionHadlers {
    /**
     *  json格式
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public Map errorHandler(MethodArgumentNotValidException ex) {
        BindingResult result = ex.getBindingResult();
        return analysis(result);

    }

    /**
     * 表单格式
     */
    @ExceptionHandler(value = BindException.class)
    public Map errorHandler(BindException ex) {
        BindingResult result = ex.getBindingResult();
        return analysis(result);
    }

    /**
     * 拦截所有运行时的全局异常
     * @param errorMsg
     * @return
     */
    @ExceptionHandler(Exception.class)
    @ResponseBody //返回 JOSN
    public Result ErrorTest(Exception errorMsg){
        HashMap<String, Object> map = new HashMap<>();
       return Result.error(400,errorMsg.getMessage());
    }

    /**
     * 拦截所有自定义运行时的全局异常
     * @param errorMsg
     * @return
     */
    @ExceptionHandler(SellException.class)
    @ResponseBody
    public Result ErrorTest(SellException errorMsg){
        HashMap<String, Object> map = new HashMap<>();
       return Result.error(errorMsg.getCode(),errorMsg.getMessage());
    }
    private Map  analysis(BindingResult result){
        StringBuilder errorMsg = new StringBuilder();
        for (ObjectError error : result.getAllErrors()) {
            errorMsg.append(error.getDefaultMessage()).append(",");
        }
        StringBuilder analysis = errorMsg.delete(errorMsg.length() - 1, errorMsg.length());
        Map map = new HashMap();
        map.put("code", 400);
        map.put("message", analysis.toString());
        return map;
    }

    /**
     * 将CheckedException转换为UncheckedException.
     */
    public static RuntimeException unchecked(Exception e) {
        if (e instanceof RuntimeException) {
            return (RuntimeException) e;
        } else {
            return new RuntimeException(e);
        }
    }

    /**
     * 将ErrorStack转化为String.
     */
    public static String getStackTraceAsString(Throwable e) {
        if (e == null){
            return "";
        }
        StringWriter stringWriter = new StringWriter();
        e.printStackTrace(new PrintWriter(stringWriter));
        return stringWriter.toString();
    }

    /**
     * 判断异常是否由某些底层的异常引起.
     */
    @SuppressWarnings("unchecked")
    public static boolean isCausedBy(Exception ex, Class<? extends Exception>... causeExceptionClasses) {
        Throwable cause = ex.getCause();
        while (cause != null) {
            for (Class<? extends Exception> causeClass : causeExceptionClasses) {
                if (causeClass.isInstance(cause)) {
                    return true;
                }
            }
            cause = cause.getCause();
        }
        return false;
    }

    /**
     * 在request中获取异常类
     * @param request
     * @return
     */
    public static Throwable getThrowable(HttpServletRequest request){
        Throwable ex = null;
        if (request.getAttribute("exception") != null) {
            ex = (Throwable) request.getAttribute("exception");
        } else if (request.getAttribute("javax.servlet.error.exception") != null) {
            ex = (Throwable) request.getAttribute("javax.servlet.error.exception");
        }
        return ex;
    }

}
